home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 25
/
Cream of the Crop 25.iso
/
compress
/
tar321__.zip
/
SOURCES.ZIP
/
RESTORE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1997-03-14
|
17KB
|
597 lines
/* restore.c - extract regular files from (tape) archive.
* This is a part of the Tar program (see file tar.c)
* Author: T.V.Shaporev
* Creation date: 11 Mar 1993
*/
#include <stdio.h>
#include <errno.h>
#include "sysup.h"
#include "modern.h"
#ifdef MODERN
# include <string.h>
#else
char *strncpy();
int strlen();
#endif
#ifdef MSDOS
# include <dos.h>
# include <stdlib.h>
#else
int access(), creat(), open(), close(), link(), unlink();
int write(), chown(), utime();
char *malloc();
long lseek();
void free();
#endif
#include "lzwbits.h"
#include "lzwhead.h"
#include "compress.h"
#include "zippipe.h"
#include "crc32.h"
#include "define.h"
#include "lzpack.h"
/* Reneaming will expand name for 5 characters at most */
char ofname[MAXTNAME+8+1];
void extwrerr()
{
(void)fprintf(myout, "Tar: error extracting \'%s\'\n", ofname);
done(EWRITE);
}
#ifdef MSDOS
static void setime __ARGS__(( int, long ));
static void setime(h, mt)
int h; long mt;
{
struct date d;
struct time t;
unsigned short f[2]; /* DOS file timestamp */
extern int setftime();
if (m_flag) return;
unixtodos(mt, &d, &t);
f[0] = (t.ti_hour << 11) | (t.ti_min << 5) | (t.ti_sec >> 1);
f[1] = ((d.da_year - 1980) << 9) | (d.da_mon << 5) | d.da_day;
(void)setftime(h, &f);
}
#define wcnt_type unsigned short
#define MAXWARN 8
static renamed = FALSE;
static wcnt_type wcount = 0;
static nwarn = 0;
static struct { wcnt_type lru; char wnm[MAXTNAME]; } wlist[MAXWARN];
static void wrename __ARGS__(( char * ));
static void wrename(n)
char *n;
{
register i;
renamed = FALSE;
for (i=0; i<nwarn; i++) {
if (strncmp(wlist[i].wnm, n, MAXTNAME) == 0) {
wlist[i].lru = wcount++; return;
}
}
(void)printf("Tar: warning: renamed to \'%s\'\n", n);
if (nwarn < MAXWARN) {
i = nwarn++;
} else {
register j;
/* Find the least recently used entry */
for (i=0, j=1; j<MAXWARN; j++) {
if (wlist[j].lru < wlist[i].lru) i = j;
}
}
(void)strncpy(wlist[i].wnm, n, MAXTNAME);
wlist[i].lru = wcount++;
}
#define CH_DOT '-'
#define CH_BAD '$'
static void uname __ARGS__(( char * ));
static void uname(fname) /* convert UNIX file name to DOS */
char fname[];
{
static char invalid[] = "^+=/[]:;\',?*\\<>|\".";
register char *p = fname;
register i, offext/* offset to file name extension */;
register j, limcpy, tmpren;
if (p[1] == ':' && (p[0]>='A' && p[0]<='Z' || p[0]>='a' && p[0]<='z'))
p += 2;
tmpren = FALSE;
while (*p) {
if (*p == '/') {
++p; /* Forget dir name changes */ tmpren = FALSE;
}
for (offext=i=0; p[i] && p[i]!='/'; i++) {
if (p[i] == '.') {
if (i == 0) {
if (p[1]=='.' && (p[2]=='/' || p[2]=='\0')) {
/* This is '..' directory, skip */ ++i;
} else if (p[1]!='/' && p[1]!='\0') {
/* This is not current directory */
p[0] = CH_DOT; tmpren = TRUE;
}
} else {
if (offext) {
p[offext] = CH_DOT; tmpren = TRUE;
}
offext = i;
}
} else if (p[i]<=' ' || p[i]>'~' || strchr(invalid, p[i])) {
p[i] = CH_BAD; tmpren = TRUE;
}
}
if (!offext) offext = i;
limcpy = MAXTNAME - (int)(p-fname) - offext;
i -= offext;
if (offext <= 8) {
j = offext;
} else {
(void)strncpy(p+8, p+offext, i>4 ? 4 : limcpy);
tmpren = TRUE;
j = 8;
}
if (i <= 4) {
j += i;
} else {
(void)strncpy(p+(offext>8 ? 12 : offext+4), p+i+offext, limcpy-i);
tmpren = TRUE;
j += 4;
}
p += j;
}
if (tmpren) renamed = TRUE;
}
#else
# define setime(h,t)
# define uname(s)
#endif
int makedir __ARGS__((char *, int));
int testdir __ARGS__((char *));
/*ARGSUSED*/ int makedir(p, to_print)
char *p; int to_print;
{
#ifdef UNIX
# ifdef RMKDIR
if (mkdir(p, 0777) != 0 && to_print) {
(void)fprintf(myout, "Tar: can\'t create directory \'%s\'\n", p);
return ERROR;
}
# else
switch (bincall("mkdir", p)) {
case 0: break;
case -1: (void)fprintf(myout, "Tar: fault run mkdir!\n");
default: done(0);
}
# endif
if (!o_flag) (void)chown(p,(int)st.st_uid,(int)st.st_gid);
#endif
#ifdef MSDOS
if (mkdir(p) != 0 && to_print) {
(void)fprintf(myout, "Tar: can\'t create directory \'%s\'\n", p);
return ERROR;
}
#endif
return 0;
}
int testdir(p)
char *p;
{
register j;
register k = FALSE;
#ifndef UNIX
register char *q = p;
#endif
#ifdef MSDOS
renamed = FALSE;
#endif
for (j=1; j<MAXTNAME && p[j]; j++) {/* check directories */
if (p[j] == '/') {
p[j] = 0;
#ifndef UNIX
uname(q); q = p + j + 1;
#endif
if (access(p, 1) < 0) {
if (makedir(p, TRUE) != 0) return ERROR;
k = TRUE;
}
p[j] = '/';
}
}
#ifdef MSDOS
if (renamed && v_flag) wrename(p);
#endif
return k;
}
long thisread;
int arcget __ARGS__((void))
{
if (v_flag && !(thisread & 07777)) percent(thisread, st.st_size);
return thisread<st.st_size ? (++thisread, readbyte()) : EOF;
}
static int o_file, indput;
static long thiscsum;
static void dstput(c)
int c;
{
thiscsum += c; ((unsigned char *)pk_out)[indput++] = c;
if (indput >= pksize) {
if (write(o_file, pk_out, pksize) != pksize) {
if (v_flag) (void)fprintf(myout, "\n");
extwrerr();
}
indput = 0;
}
}
#define savename(s) ((void)strncpy(ofname,(s),MAXTNAME),ofname[MAXTNAME]='\0')
static int newfile __ARGS__(( char *, int ));
static int newfile(name, mode)
char *name; int mode;
{
#ifdef MSDOS
int h, caccess;
unsigned cmode;
register k = 0;
savename(name);
caccess = o_flag ? OA_CREATENEW : OA_TRUNCATE+OA_CREATENEW;
cmode = mapumode(mode);
if ((h = lopen4(name, OM_WRONLY, caccess, cmode)) < 0) {
if (errno == ENOENT || errno == ENOPATH) {
if ((k=testdir(name)) == TRUE)
h = lopen4(name, OM_WRONLY, caccess, cmode);
} else if (errno == EEXIST && o_flag) {
static char del[4] = "^~\'`";
register unsigned ntry = 0;
register nb, len, i, j;
char suffix[5];
int maxlen = lfn_active == TRUE ? 255: 8;
if ((len = strlen(name)) > MAXTNAME) goto end;
for (nb=len; nb>0 && name[nb-1]!='/' && name[nb-1]!=':'; nb--) {
if (name[nb] == '.') len = nb;
}
len -= nb;
do {
++ntry;
/* Convert number of try into suffix */
suffix[0] = del[ntry & 3];
for (i=1, j=ntry>>2; j; j>>=5) {
suffix[i++] = ((j & 037) < 10 ? '0': 'A'-10) + (j & 037);
}
suffix[i] = '\0';
/* Replace end of the name by suffix */
if (len < maxlen) {
(void)strcat(
strcpy(ofname+nb+
(len+i<maxlen ? len : maxlen-i), suffix),
name+nb+len);
} else {
(void)strncpy(ofname+nb+len-i, suffix, i);
}
renamed = TRUE;
h = lopen4(ofname, OM_WRONLY, caccess, cmode);
} while (h<0 && errno == EEXIST && ntry);
}
}
end:
if (h < 0) {
if (k!=ERROR) (void)fprintf(myout,"Tar: can\'t create \'%s\'\n",name);
} else {
if (renamed && v_flag) wrename(ofname);
/*if ((mode & 0777) == 0) (void)chmod(name, 1, FA_HIDDEN);*/
}
return h;
#else
register j = 0;
register h;
savename(name);
do {
if ((h = creat(name, (int)(mode & 07777))) >= 0) {
if (!o_flag) (void)chown(name, (int)st.st_uid, (int)st.st_gid);
return h;
}
} while (++j < 2 && testdir(name) == TRUE);
if (j > 1) (void)fprintf(myout, "Tar: can\'t create \'%s\'\n", name);
return ERROR;
#endif
}
static void pfile __ARGS__((char *, long, long));
static void pfile(name, bytes, blocks)
char name[]; long bytes, blocks;
{
if (v_flag) {
(void)fprintf(myout, "x %s, %ld bytes, %ld tape blocks",
name, bytes, blocks);
(void)fflush(myout);
}
}
static int xany __ARGS__((void))
{
(void)fprintf(stderr, " Extract anyway? ");
(void)fflush(stderr);
return YES_NO();
}
int restore(p)
register char *p;
{
register j;
register long bytes, blocks;
static char no_mem[] = "\nTar: no memory to unpack.";
static char e[] = " \n";
short nx=0, allx; long l=0, xinfo;
int multy = FALSE; /* Multyvolume processing flag */
extern int soctul __ARGS__((char*, long*));
#ifdef MSDOS
renamed = FALSE;
#endif
if (hblock->m.filetype == GF_MUL) {
(void)soctul(hblock->x.offset, &xinfo);
multy = TRUE;
} else {
if ((nx = isextent(&allx, &xinfo)) > 0) multy = TRUE;
}
bytes = codesize > st.st_size ? codesize : st.st_size;
blocks = (st.st_size + BLKSIZE-1)/BLKSIZE;
if (pktype == PKfLZW && !multy && st.st_size >= codesize) {
j = strlen(p);
if (p[--j] != 'Z' || p[--j] != '.') goto regular;
p[j] = '\0';
uname(p);
if ((o_file = newfile(p, st.st_mode)) < 0) {
skipfile(); return ERROR;
}
pfile(p, bytes, blocks);
p[j] = '.';
(void)z_getmem(BITS);
thisread = 0; indput = 0; thiscsum = 0;
if ((j = dbegin(arcget)) == 0) {
do {
j = dpiece(pk_out, pksize);
if (j > 0) {
if (write(o_file, pk_out, j) != j) {
if (v_flag) (void)fprintf(myout, "\n");
extwrerr();
}
if (v_flag) percent(thisread, st.st_size);
}
} while (j == pksize);
(void)fprintf(myout, v_flag ? e : e+sizeof(e)-2);
goto xend;
} else if (j > 0) {
if (v_flag) (void)fprintf(myout, " is not in compressed format\n");
} else {
if (!xany()) done(ESMALL);
}
bacouple(); z_relmem();
}
regular:
uname(p);
if (nx > 1 || (hblock->m.filetype == GF_MUL && xinfo > 0)) {
/* Multivolume processing */
if ((o_file = open(p, OM_WRONLY)) >= 0) {
savename(p);
if ((l=lseek(o_file, 0L, 2)) == -1L) {
(void)fprintf(myout, " Tar: \'%s\' seek error\n", p);
goto fault;
}
if (hblock->m.filetype == GF_MUL && l != xinfo) {
if (w_flag) {
(void)fprintf(stderr,
" Tar: \'%s\' mismatch size. Append? ", p);
(void)fflush(stderr);
if (YES_NO()) goto opened;
} else {
(void)fprintf(myout,
" Tar: warning: \'%s\' mismatch size\n", p);
}
l = lseek(o_file, xinfo, 0);
}
goto opened;
} else if (errno == ENOENT) {
if (w_flag) {
(void)fprintf(stderr,
" Tar: \'%s\' does not exist.", p);
if (!xany()) goto fault;
} else {
(void)fprintf(myout,
" Tar: warning: \'%s\' does not exist\n", p);
goto fault;
}
} else {
(void)fprintf(myout, "Tar: can\'t append \'%s\'\n", p);
goto fault;
}
}
if ((o_file = newfile(p, st.st_mode)) < 0) goto fault;
opened:
pfile(ofname, bytes, blocks);
if (st.st_size >= codesize || multy) {/* file was not packed */
if (v_flag) {
if (nx > 0) {
(void)fprintf(myout," [extent #%d of %d]", nx, allx);
} else if (hblock->m.filetype == GF_MUL) {
(void)fprintf(myout," [");
if (l != xinfo)
(void)fprintf(myout,"from %ld - ", xinfo);
(void)fprintf(myout,"append @%ld]", l);
}
(void)fprintf(myout, "\n");
}
(void)readarch(o_file, st.st_size);
if (nx > 1 && nx == allx && lseek(o_file, 0L, 2) != xinfo) {
/* last extent extracted, so check for total file size */
(void)fprintf(myout,"Tar: warning: \'%s\' changed size\n",ofname);
}
} else {/* file was packed */
if (!pk_out) pk_out = malloc(pksize);
if (hblock->m.srcsum[1] != 'x') {/* Old decompression */
if (!pk_out || lzgetmem()) {
(void)fprintf(myout, "%s\n", no_mem);
done(ESMALL);
}
thisread = 0; indput = 0; thiscsum = 0;
l = lzdecode(arcget, dstput, codesize);
(void)fprintf(myout, v_flag ? e : e+sizeof(e)-2);
if (indput > 0 && write(o_file, pk_out, indput) != indput)
extwrerr();
if (l != codesize) {
(void)fprintf(myout, "Tar: \'%s\' decode error\n", ofname);
if (!i_flag) done(EINTER);
}
if (thiscsum != longcsum) {
(void)fprintf(myout, "Tar: \'%s\' checksum error\n", ofname);
}
} else {/* Inflation */
if (!pk_out || unzalloc()) {
(void)fprintf(myout, "%s\n", no_mem);
done(ESMALL);
}
thisread = 0; indput = 0; thiscsum = 0;
if (unzopen(arcget, ZIP_RAW)) {
(void)fprintf(myout, "Tar: unzip error: %s\n",
ziperrlist[ziperror]);
done(EINTER);
}
do {
j = unzread(pk_out, pksize);
if (j > 0) {
if (write(o_file, pk_out, j) != j) {
if (v_flag) (void)fprintf(myout, "\n");
extwrerr();
}
if (v_flag) percent(thisread, st.st_size);
}
} while (j == pksize);
(void)fprintf(myout, v_flag ? e : e+sizeof(e)-2);
if (j != -1) {
if ((j = unzclose()) == 0) {
if (getcrc() != longcsum) j = ziperror = BADCRC;
}
}
if (j) {
(void)fprintf(myout,"Unzip %s: %s\n",
(j == -1 ? "error" : "warning"), ziperrlist[ziperror]);
if (j == -1) done(EINTER);
}
}
}
xend:
j = nx > 0 && nx < allx;
#ifdef MSDOS
if (!j) setime(o_file, st.st_mtime);
#endif
(void)close(o_file);
return j;
fault:
if (o_file >= 0) (void)close(o_file);
skipfile();
return ERROR;
}
void makelink(fname, lname)
char *fname, *lname;
{
#ifdef MSDOS
# define BUFSIZE 8192
char *buffer = NULL;
int bufsize = BUFSIZE;
#endif
register j;
#ifdef UNIX
(void)unlink(fname);
if ((j = link(lname, fname)) < 0) {
if (testdir(fname) == TRUE) j = link(lname, fname);
}
if (j < 0)
(void)fprintf(myout,
"Tar: can\'t link \'%s\' to \'%s\'\n", fname, lname);
else
#endif
#ifdef MSDOS
if (l_flag) {/* copy file */
int inp, out;
char *buffer; int bufsize;
long rsize, mtime;
if ((buffer = malloc(BUFSIZE)) == NULL) {
if (pk_out) {
buffer = pk_out;
bufsize = pksize;
} else {
buffer = (char *)hblock;
bufsize = BLKSIZE;
}
}
if ((inp = open(lname, OM_RDONLY)) < 0) {
cantopen(lname); goto quit;
}
if ((out = newfile(fname, st.st_mode)) < 0) {
(void)close(inp); goto quit;
}
rsize = st.st_size;
mtime = st.st_mtime;
do {
if ((j = read(inp, buffer, bufsize)) > 0) {
rsize -= j;
if (write(out, buffer, j) != j) {
extwrerr(); j = ERROR;
}
}
} while (j == bufsize);
if (j >= 0) setime(out, mtime);
(void)close(out);
(void)close(inp);
if (j < 0) goto quit;
if (v_flag) (void)fprintf(myout, "x %s copied from %s\n", fname, lname);
if (rsize != 0)
(void)fprintf(myout,
"Tar: warning \'%s\' real size differs from the recorded\n",fname);
} else
#endif
if (v_flag) (void)fprintf(myout, "x %s linked to %s\n", fname, lname);
#ifdef MSDOS
quit:
if (buffer != NULL && bufsize == BUFSIZE) free(buffer);
#endif
}